package org.light.verb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.light.core.Verb;
import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Dropdown;
import org.light.domain.Field;
import org.light.domain.JavascriptBlock;
import org.light.domain.JavascriptMethod;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.domain.Type;
import org.light.easyui.EasyUIPositions;
import org.light.exception.ValidateException;
import org.light.utils.DomainUtil;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;

public class FilterExcel extends Verb implements EasyUIPositions {
	protected SearchByFields search = new SearchByFields();
	protected Set<Field> deniedFields = new TreeSet<>();
	
	@Override
	public Method generateDaoImplMethod() throws Exception{
		return null;
	}
	@Override
	public Method generateDaoMethodDefinition()  throws Exception{
		return null;
	}
	@Override
	public Method generateServiceMethodDefinition()  throws Exception{
		return null;
	}
	@Override
	public Method generateServiceImplMethod()  throws Exception{
		return null;
	}

	public FilterExcel(){
		super();
		this.setLabel("Excel过滤");
	}
	
	public FilterExcel(Domain domain) throws ValidateException{
		super();
		this.domain = domain;
		this.denied = domain.isVerbDenied("FilterExcel");
		this.search = new SearchByFields(domain);
		this.setVerbName("Filter"+StringUtil.capFirst(this.domain.getPlural())+"Excel");
		this.setLabel("Excel过滤");
		if  (domain.getLanguage().equalsIgnoreCase("english"))  this.setLabel("FilterExcel");
	}

	@Override
	public Method generateControllerMethod()  throws Exception{
		if (this.denied)
			return null;
		else {
			this.search.setDomain(this.domain);		
			Method method = new Method();
			method.setStandardName(this.getVerbName());
			method.addSignature(new Signature(1,"c","*gin.Context"));
			method.addAdditionalImport(DomainUtil.packagetokenToGoPackageFolder(this.domain.getProjectName(),this.domain.getPackageToken()+".utils"));
			
			List<Writeable> sList = new ArrayList<Writeable>();
			sList.add(new Statement(2000L,1,"ignoreMap := make(map[string]bool)"));
			long serial = 3000L;
			for (Field f : this.domain.getSearchFields()) {
				if (!deniedFields.contains(f)) {
					sList.add(new Statement(serial+1000L,1,"if c.Query(\""+f.getLowerFirstFieldName()+"\") == \"\" {"));
					sList.add(new Statement(serial+2000L,2,"ignoreMap[\""+f.getLowerFirstFieldName()+"\"] = true"));
					sList.add(new Statement(serial+3000L,1,"}"));
					serial += 4000L;
				}
			}
			for (Field f : this.domain.getSearchFields()) {
				if (!deniedFields.contains(f)) {
					if (f.getFieldType().equalsIgnoreCase("bool")) {
						sList.add(new Statement(serial,1,f.getLowerFirstFieldName()+", _ := strconv.ParseBool(c.Query(\""+f.getLowerFirstFieldName()+"\"))"));
					} else if (f.getFieldType().equalsIgnoreCase("string")) {
						sList.add(new Statement(serial,1,f.getLowerFirstFieldName()+" := c.Query(\""+f.getLowerFirstFieldName()+"\")"));
					} else if (f.getFieldType().equalsIgnoreCase("int64")) {
						sList.add(new Statement(serial,1,f.getLowerFirstFieldName()+", _ := strconv.ParseInt(c.PostForm(\""+f.getLowerFirstFieldName()+"\"), 10, 64)"));
					} else if (f.getFieldType().equalsIgnoreCase("int")) {
						sList.add(new Statement(serial,1,f.getLowerFirstFieldName()+", _ := strconv.Atoi(c.PostForm(\""+f.getLowerFirstFieldName()+"\"))"));
					}else if (f.getFieldType().equalsIgnoreCase("int32")) {
						sList.add(new Statement(serial,1,f.getLowerFirstFieldName()+", _ := strconv.ParseInt(c.PostForm(\""+f.getLowerFirstFieldName()+"\"), 10, 32)"));
					} else if (f.getFieldType().equalsIgnoreCase("float")||f.getFieldType().equalsIgnoreCase("float64")) {
						sList.add(new Statement(serial,1,f.getLowerFirstFieldName()+", _ := strconv.ParseFloat(c.Query(\""+f.getLowerFirstFieldName()+"\"), 64)"));
					} else if (f.getFieldType().equalsIgnoreCase("float32")) {
						sList.add(new Statement(serial,1,f.getLowerFirstFieldName()+", _ := strconv.ParseFloat(c.Query(\""+f.getLowerFirstFieldName()+"\"), 32)"));
					}
					serial += 1000L;
				}
			}
			sList.add(new Statement(serial,1,""+this.domain.getLowerFirstDomainName()+" := "+this.domain.getDomainSuffix()+"."+this.domain.getCapFirstDomainNameWithSuffix()+"{"));
			serial += 1000L;
			for (Field f : this.domain.getSearchFields()) {
				if (!deniedFields.contains(f)) {
					if (f.getFieldType().equalsIgnoreCase("int32")) sList.add(new Statement(serial,2,f.getCapFirstFieldName()+":      int32("+f.getLowerFirstFieldName()+"),"));
					else sList.add(new Statement(serial,2,f.getCapFirstFieldName()+":      "+f.getLowerFirstFieldName()+","));
					serial += 1000L;
				}
			}
			sList.add(new Statement(serial,1,"}"));
			sList.add(new Statement(serial+1000L,0,""));
			sList.add(new Statement(serial+3000L,1,"list := "+this.domain.getServiceimplSuffix()+".Search"+this.domain.getCapFirstPlural()+"ByFields("+this.domain.getLowerFirstDomainName()+",ignoreMap)"));
			sList.add(new Statement(serial+4000L,1,"var contents [][]interface{}"));
			if  (domain.getLanguage().equalsIgnoreCase("english"))  {
				sList.add(new Statement(serial+5000L,1,"sheetName := \""+this.domain.getText()+" Information\""));
			}else {
				sList.add(new Statement(serial+5000L,1,"sheetName := \""+this.domain.getText()+"信息表\""));			
			}
			sList.add(new Statement(serial+6000L,1,"headers := [] string"+this.domain.generateFieldLabelsArrayStr(this.domain.getFields())));
			sList.add(new Statement(serial+7000L,1,"isImages := [] bool"+this.domain.generateIsImageFieldsArrayStr(this.domain.getFields())));
			
			sList.add(new Statement(serial+8000L,1,"for _, "+this.domain.getLowerFirstDomainName()+" := range list {"));
			serial += 9000L;
			for (Field f:this.domain.getFields()) {
				if (f instanceof Dropdown) {
					Dropdown dp = (Dropdown)f;
					sList.add(new Statement(serial,2,f.getLowerFirstFieldName()+" := "+this.domain.getLowerFirstDomainName()+".Get"+f.getCapFirstFieldName()+"()"));
					sList.add(new Statement(serial+1000L,2,"var "+f.getLowerFirstFieldName()+"Type0 "+this.domain.getDomainSuffix()+"."+dp.getTarget().getCapFirstDomainNameWithSuffix()));
					sList.add(new Statement(serial+2000L,2,f.getLowerFirstFieldName()+"Name0 := \"\""));
					sList.add(new Statement(serial+3000L,2,"if "+f.getLowerFirstFieldName()+" != 0 {"));
					sList.add(new Statement(serial+4000L,3,f.getLowerFirstFieldName()+"Type0 = "+this.domain.getServiceimplSuffix()+".Find"+dp.getTarget().getCapFirstDomainName()+"By"+dp.getTarget().getDomainId().getCapFirstFieldName()+"("+f.getLowerFirstFieldName()+")"));
					sList.add(new Statement(serial+5000L,3,"if "+f.getLowerFirstFieldName()+"Type0.Get"+dp.getTarget().getDomainId().getCapFirstFieldName()+"() != 0 {"));
					sList.add(new Statement(serial+6000L,4,f.getLowerFirstFieldName()+"Name0 = "+f.getLowerFirstFieldName()+"Type0.Get"+dp.getTarget().getDomainName().getCapFirstFieldName()+"()"));
					sList.add(new Statement(serial+7000L,3,"}"));
					sList.add(new Statement(serial+8000L,2,"}"));
					serial += 9000L;
				}
			}				
			sList.add(new Statement(serial,0,""));
			String sc = "row := [] interface{} {";
			for (Field f:this.domain.getFields()) {
				if (f instanceof Dropdown) {
					Dropdown dp = (Dropdown)f;
					sc += dp.getAliasName() + "Name0,";
				}else {
					if (f.getFieldType().equalsIgnoreCase("string")||f.getFieldType().equalsIgnoreCase("image")) {
						sc += this.domain.getLowerFirstDomainName()+".Get"+f.getCapFirstFieldName()+"(),";
					} else if (f.getFieldType().equalsIgnoreCase("int64")) {
						sc += "strconv.FormatInt("+this.domain.getLowerFirstDomainName()+".Get"+f.getCapFirstFieldName()+"(), 10),";
					} else if (f.getFieldType().equalsIgnoreCase("int")) {
						sc += "strconv.Itoa("+this.domain.getLowerFirstDomainName()+".Get"+f.getCapFirstFieldName()+"()),";
					} else if (f.getFieldType().equalsIgnoreCase("int32")) {
						method.addAdditionalImport("fmt");
						sc += "fmt.Sprint("+this.domain.getLowerFirstDomainName()+".Get"+f.getCapFirstFieldName()+"()),";
					}  else if (f.getFieldType().equalsIgnoreCase("float")||f.getFieldType().equalsIgnoreCase("float64")) {
						sc += "strconv.FormatFloat("+this.domain.getLowerFirstDomainName()+".Get"+f.getCapFirstFieldName()+"(), 'f', 4, 64),";
					} else if (f.getFieldType().equalsIgnoreCase("float32")) {
						sc += "strconv.FormatFloat("+this.domain.getLowerFirstDomainName()+".Get"+f.getCapFirstFieldName()+"(), 'f', 4, 32),";
					}else if (f.getFieldType().equalsIgnoreCase("bool")) {
						sc += "strconv.FormatBool("+this.domain.getLowerFirstDomainName()+".Get"+f.getCapFirstFieldName()+"()),";
					}
				}
			}
			if (this.domain.getFields()!=null && this.domain.getFields().size()>0) {
				sc = sc.substring(0,sc.length()-1);
			}
			sc += "}";
			sList.add(new Statement(serial+18000L,2,sc));
			sList.add(new Statement(serial+18000L,2,"contents = append(contents, row)"));
			sList.add(new Statement(serial+19000L,1,"}"));
			sList.add(new Statement(serial+20000L,0,""));
			sList.add(new Statement(serial+21000L,1,"c.Header(\"Content-Type\", \"application/octet-stream\")"));
			sList.add(new Statement(serial+22000L,1,"c.Header(\"Content-Disposition\", \"attachment; filename=\"+\""+this.domain.getLowerFirstPlural()+".xlsx\")"));
			sList.add(new Statement(serial+23000L,1,"c.Header(\"Content-Transfer-Encoding\", \"binary\")"));
			sList.add(new Statement(serial+24000L,0,""));
			sList.add(new Statement(serial+25000L,1,"xlsx := utils.ExportExcelWorkbookWithImage(sheetName, headers, contents, isImages)"));
			sList.add(new Statement(serial+26000L,1,"xlsx.Write(c.Writer)"));
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;
		}
	}
	@Override
	public JavascriptBlock generateEasyUIJSButtonBlock() throws Exception {
		return null;
	}
	@Override
	public JavascriptMethod generateEasyUIJSActionMethod() throws Exception {
		if (this.denied)
			return null;
		else {
			Domain domain = this.domain;
			JavascriptMethod method = new JavascriptMethod();
			method.setSerial(200);
			method.setStandardName("filter"+domain.getPlural()+"Excel");
					
			StatementList sl = new StatementList();
			sl.add(new Statement(1000,1, "params = {"));
			long serial = 2000;
			for (Field f: domain.getSearchFields()){
				if (f instanceof Dropdown)
					sl.add(new Statement(serial,2, f.getLowerFirstFieldName()+":$(\"#ffsearch\").find(\"#"+f.getLowerFirstFieldName()+"\").combobox(\"getValue\"),"));
				else if (!f.getFieldType().equalsIgnoreCase("boolean"))
					sl.add(new Statement(serial,2, f.getLowerFirstFieldName()+":$(\"#ffsearch\").find(\"#"+f.getLowerFirstFieldName()+"\").val(),"));
				else 
					sl.add(new Statement(serial,2, f.getLowerFirstFieldName()+":parseBoolean($(\"#ffsearch\").find(\"#"+f.getLowerFirstFieldName()+"\").val()),"));
				serial+=1000;
			}	
			sl.add(new Statement(serial,1, "};"));
			sl.add(new Statement(serial+1000,1, "var params0 = $.param(params);"));
			sl.add(new Statement(serial+2000,1, "document.location.href = \"../"+this.domain.getControllerPackagePrefix()+this.domain.getLowerFirstDomainName()+domain.getControllerNamingSuffix()+"/filter"+this.domain.getCapFirstPlural()+"Excel?\" + params0;"));
		    
			method.setMethodStatementList(sl);
			return method;	
		}
	}
}
